package com.pearl.jacksoncore.demo.databind.anno;

import com.fasterxml.jackson.annotation.JsonEnumDefaultValue;
import com.fasterxml.jackson.annotation.JsonRootName;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.databind.annotation.JsonTypeIdResolver;
import com.fasterxml.jackson.databind.ser.impl.SimpleBeanPropertyFilter;
import com.fasterxml.jackson.databind.ser.impl.SimpleFilterProvider;
import com.pearl.jacksoncore.demo.pojo.Org;
import com.pearl.jacksoncore.demo.pojo.User;

import java.io.File;
import java.time.LocalDateTime;
import java.util.*;

/**
 * @author TD
 * @version 1.0
 * @date 2024/3/20
 */
public class JacksonAnnotationsTest {
    public static void main(String[] args) throws JsonProcessingException {
        // 1. @JsonIgnore
        ObjectMapper objectMapper = new ObjectMapper();
        // POJO -> JSON
        UserInfo user = new UserInfo();
        user.setId(1767798780627279333L);
        user.setName("老三");
        user.setAge(25);
/*        String json = objectMapper.writeValueAsString(user);
        System.out.println(json);*/

        // JSON -> POJO
        String userJson = "{\"id\":1767798780627279873,\"name\":\"坤坤\",\"age\":18,\"org\":null,\"roleList\":null}";
/*        UserInfo readUserByJson = objectMapper.readValue(userJson, UserInfo.class);
        System.out.println(readUserByJson);*/

        // 2. @JsonFormat
        user.setBirthdayDate(new Date());
        user.setBirthdayLocalDateTime(LocalDateTime.now());
        String json = objectMapper.writeValueAsString(user);
        System.out.println(json);

        UserInfo readUserByJson = objectMapper.readValue(json, UserInfo.class);
        System.out.println(readUserByJson);

        // 3. @JsonInclude
        user.setName(null);
        String jsonInclude = objectMapper.writeValueAsString(user);
        System.out.println(jsonInclude);

        // 4. @JsonProperty
        user.setAge(25);
        String jsonProperty = objectMapper.writeValueAsString(user);
        System.out.println(jsonProperty);

        // 5 @JsonAlias
        String userAliasJson = "{\"id\":1767798780627279873,\"username\":\"坤坤\",\"userAge\":18,\"org\":null,\"roleList\":null}";
        UserInfo readUserByAliasJson = objectMapper.readValue(userAliasJson, UserInfo.class);
        System.out.println(readUserByAliasJson);

        // 6. @JsonIgnoreType
        String userJsonIgnoreTypeStr = "{\"id\":1767798780627279873,\"username\":\"坤坤\",\"userAge\":18,\"org\":{\"id\":1699967647585800192,\"orgName\":\"阿里巴巴\",\"address\":\"浙江杭州\"},\"roleList\":null}";
        UserInfo readUserByJsonIgnoreType = objectMapper.readValue(userJsonIgnoreTypeStr, UserInfo.class);
        System.out.println(readUserByJsonIgnoreType);

        // 7. @JsonIgnoreProperties
        user.setPassword("888888");
        String userIgnorePropertiesStr = "{\"id\":1767798780627279873,\"username\":\"坤坤\",\"userAge\":18,\"org\":{\"id\":1699967647585800192,\"orgName\":\"阿里巴巴\",\"address\":\"浙江杭州\"},\"roleList\":null}";
        UserInfo readUserByIgnoreProperties = objectMapper.readValue(userIgnorePropertiesStr, UserInfo.class);
        System.out.println(readUserByIgnoreProperties);

        String jsonIgnorePropertiesStr = objectMapper.writeValueAsString(user);
        System.out.println(jsonIgnorePropertiesStr);
        UserInfo readUserByJsonIgnorePropertiesStr = objectMapper.readValue(jsonIgnorePropertiesStr, UserInfo.class);
        System.out.println(readUserByJsonIgnorePropertiesStr);

        // 8. @JsonPropertyOrder
        String JsonPropertyOrderStr = objectMapper.writeValueAsString(user);
        System.out.println(JsonPropertyOrderStr);

        // 9. @JsonGetter
        user.setSex("男");
        String jsonGettersStr = objectMapper.writeValueAsString(user);
        System.out.println(jsonGettersStr);

        String jsonGetterStr = "{\"userSex\":\"男\",\"id\":1767798780627279873,\"username\":\"坤坤\",\"userAge\":18,\"org\":{\"id\":1699967647585800192,\"orgName\":\"阿里巴巴\",\"address\":\"浙江杭州\"},\"roleList\":null}";
        UserInfo readUserByJsonGetter = objectMapper.readValue(jsonGetterStr, UserInfo.class);
        System.out.println(readUserByJsonGetter);

        // 10. @JsonSetter
        user.setPhone("13899996666");
        String jsonSettersStr = objectMapper.writeValueAsString(user);
        System.out.println(jsonSettersStr);

        String jsonSetterStr = "{\"mobilePhone\":\"13899996666\",\"userSex\":\"男\",\"id\":1767798780627279873,\"username\":\"坤坤\",\"userAge\":18,\"org\":{\"id\":1699967647585800192,\"orgName\":\"阿里巴巴\",\"address\":\"浙江杭州\"},\"roleList\":null}";
        UserInfo readUserByJsoSetter = objectMapper.readValue(jsonSetterStr, UserInfo.class);
        System.out.println(readUserByJsoSetter);

        // 11. @JsonValue
        user.setGender(GenderEnum.WOMAN);
        String jsonValuesStr = objectMapper.writeValueAsString(user);
        System.out.println(jsonValuesStr);

        // 12. @JsonKey
        Org org1 = new Org();
        org1.setId(1765672919981232128L);
        org1.setOrgName("阿里巴巴");

        Org org2 = new Org();
        org2.setId(1772078846569590784L);
        org2.setOrgName("支付宝");


        Map<Org, String> map = new HashMap<>();
        map.put(org1, "顶级机构");
        map.put(org2, "下级机构");

        String orgStr = objectMapper.writeValueAsString(map);
        System.out.println(orgStr);

        // 13. @JsonAnySetter
        String jsonAnySetterStr = "{\"idCard\":\"43268825255522222\",\"userSex\":\"男\",\"id\":1767798780627279873,\"username\":\"坤坤\",\"userAge\":18,\"org\":{\"id\":1699967647585800192,\"orgName\":\"阿里巴巴\",\"address\":\"浙江杭州\"},\"roleList\":null}";
        UserInfo readUserByAnySetter = objectMapper.readValue(jsonAnySetterStr, UserInfo.class);
        System.out.println(readUserByAnySetter);

        // 14. @JsonAnyGetter
        String jsonStrByAnySetter = objectMapper.writeValueAsString(readUserByAnySetter);
        System.out.println(jsonStrByAnySetter);

        // 15. @JacksonInject
        // 设置默认值
        InjectableValues.Std injectableValues = new InjectableValues.Std();
        injectableValues.addValue("phone", "13788889999");
        objectMapper.setInjectableValues(injectableValues);
        // 反序列化
        String jsonInjectStr = "{\"phone\":\"13566666665\"}";
        UserInject readUserByInject = objectMapper.readValue(jsonInjectStr, UserInject.class);
        System.out.println(readUserByInject);

        // 15. @@JsonCreator
        String jsonCreatorStr = "{\"phone\":\"13566666665\",\"name\":\"张三\"}";
        UserInject readUserByCreator = objectMapper.readValue(jsonCreatorStr, UserInject.class);
        System.out.println(readUserByCreator);

        // 16. @JsonTypeInfo、@JsonTypeName、@JsonTypeId、@JsonTypeName
        Student student = new Student();
        student.setName("坤坤童鞋");
        student.setTypeId("sut11111111");

        Teacher teacher = new Teacher();
        teacher.setName("悠上老师");
        teacher.setTypeId("tea1111111");

        List<Person> personList = new ArrayList<>();
        personList.add(student);
        personList.add(teacher);

        PersonVO personVO = new PersonVO();
        personVO.setPersonList(personList);


        String jsonStrByPerson = objectMapper.writeValueAsString(personVO);
        System.out.println(jsonStrByPerson);

        PersonVO readUserByPerson = objectMapper.readValue(jsonStrByPerson, PersonVO.class);
        System.out.println(readUserByPerson);

        // 17. @JsonView
        LoginUser loginUser = new LoginUser();
        loginUser.setName("范冰冰");
        loginUser.setIdCard("62226203625656698");
        loginUser.setPhone("13896963636");
        loginUser.setPwd("123456");
        // 管理员
        String jsonStrByViewSensitive = objectMapper.writerWithView(UserInfoView.SensitiveView.class).writeValueAsString(loginUser);
        System.out.println(jsonStrByViewSensitive);
        // 超级管理员
        String jsonStrByVerySensitiveView = objectMapper.writerWithView(UserInfoView.VerySensitiveView.class).writeValueAsString(loginUser);
        System.out.println(jsonStrByVerySensitiveView);

        // 17. @JsonIncludeProperties
        String jsonStrByIncludeProperties = objectMapper.writeValueAsString(loginUser);
        System.out.println(jsonStrByIncludeProperties);

        String StrJsonIncludeProperties = "{\"id\":null,\"name\":\"范冰冰\",\"idCard\":\"62226203625656698\",\"phone\":\"13896963636\",\"pwd\":\"123456\"}";
        LoginUser readUserByStrJsonIncludeProperties = objectMapper.readValue(StrJsonIncludeProperties, LoginUser.class);
        System.out.println(readUserByStrJsonIncludeProperties);

        // 18. @AutoDetect
        String strJsonAutoDetect = "{\"id\":null,\"name\":\"范冰冰\",\"idCard\":\"62226203625656698\",\"phone\":\"13896963636\",\"pwd\":\"123456\"}";
        AutoDetectUser readUserByAutoDetectUser = objectMapper.readValue(strJsonAutoDetect, AutoDetectUser.class);
        System.out.println(readUserByAutoDetectUser);

        // 19. @JsonFilter
        // 添加一个过滤器，并命名为 myFilter
        SimpleFilterProvider filterProvider = new SimpleFilterProvider();
        // filterOutAllExcept : 序列化指定字段
        filterProvider.addFilter("myFilter", SimpleBeanPropertyFilter.filterOutAllExcept("name", "phone"));
        objectMapper.setFilterProvider(filterProvider);
        String jsonStrByJsonFilter = objectMapper.writeValueAsString(readUserByAutoDetectUser);
        System.out.println(jsonStrByJsonFilter);

        // 20. @JsonBackReference、@JsonManagedReference
        Company company = new Company();
        company.setName("杭州阿里巴巴");
        company.setAddress("西湖");

        Dept dept001 = new Dept();
        dept001.setName("研发部");
        dept001.setCompany(company);

        Dept dept002 = new Dept();
        dept002.setName("人事部");
        dept002.setCompany(company);

        List<Dept> deptList = new ArrayList<>();
        deptList.add(dept001);
        deptList.add(dept002);
        company.setDeptList(deptList);

        String jsonStrByReference = objectMapper.writeValueAsString(company);
        System.out.println(jsonStrByReference);

        Company companyByRead = objectMapper.readValue(jsonStrByReference, Company.class);
        System.out.println(companyByRead);

        // 20. @JsonClassDescription、@JsonPropertyDescription

        // 21. @JsonRootName
        objectMapper.enable(SerializationFeature.WRAP_ROOT_VALUE);
        objectMapper.enable(DeserializationFeature.UNWRAP_ROOT_VALUE);
        String jsonRootNameStr = objectMapper.writeValueAsString(user);
        System.out.println(jsonRootNameStr);

        // 22. @JsonRawValue
        JsonRawVO jsonRawVO = new JsonRawVO();
        jsonRawVO.setJson("{\"id\":null,\"name\":\"范冰冰\",\"idCard\":\"62226203625656698\",\"phone\":\"13896963636\",\"pwd\":\"123456\"}");
        String jsonStrByJsonRawVO = objectMapper.writeValueAsString(jsonRawVO);
        System.out.println(jsonStrByJsonRawVO);

        // 23. `@JsonEnumDefaultValue`
        objectMapper.enable(DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_USING_DEFAULT_VALUE);
        GenderEnum genderEnum = objectMapper.readValue("\"男人\"", GenderEnum.class);
        System.out.println(genderEnum);

        // 24 @JsonIdentityInfo、@JsonIdentityReference

        // 25. @JsonUnwrapped
        UnwrappedVO unwrappedVO = new UnwrappedVO("范冰冰", "明星");
        Child child = new Child("哈哈");
        unwrappedVO.setChild(child);

        String jsonStrByJsonUnwrapped = objectMapper.writeValueAsString(unwrappedVO);
        System.out.println(jsonStrByJsonUnwrapped);

        // 26. @JsonMerge
        Map<String, String> stringStringMap = new HashMap<>();
        stringStringMap.put("field3", "value3");
        ObjectWithMap objectToUpdateWith = new ObjectWithMap("James", stringStringMap);

        String newData = "{\"stringPairs\":{\"field1\":\"value1\",\"field2\":\"value2\"}}";
        ObjectWithMap update = objectMapper.readerForUpdating(objectToUpdateWith).readValue(newData);
        System.out.println(update);

        // 27. @JsonSerialize、@JsonDeserialize

        // 28. @JsonNaming
        JsonNamingVO jsonNamingVO = new JsonNamingVO();
        jsonNamingVO.setId(1455455612333L);
        jsonNamingVO.setName("测试");

        String jsonStrByJsonNamingVO = objectMapper.writeValueAsString(jsonNamingVO);
        System.out.println(jsonStrByJsonNamingVO);

        // 28. @JsonAppend
        JsonAppendVO jsonAppendVO = new JsonAppendVO();
        jsonAppendVO.setId(1455455612333L);
        jsonAppendVO.setName("测试");

        String jsonStrByjsonAppendVO = objectMapper.writeValueAsString(jsonAppendVO);
        System.out.println(jsonStrByjsonAppendVO);

        // 29. @JsonPOJOBuilder
        String strByJsonPOJOBuilder = "{\"name\":\"haha\",\"age\":2}";
        Dog dog = objectMapper.readValue(strByJsonPOJOBuilder, Dog.class);
        System.out.println(dog);

        // 30. @JsonValueInstantiator
        String strByValueInstantiatorVO = "{}";
        ValueInstantiatorVO valueInstantiatorVO = objectMapper.readValue(strByValueInstantiatorVO, ValueInstantiatorVO.class);
        System.out.println(valueInstantiatorVO);

        // 31 @JsonTypeResolver
        Data data = new Data(1L);
        Map<String, Object> mapData = new HashMap<>();
        mapData.put("longInMap", 2L);
        mapData.put("longAsField", data);
        objectMapper.enable(SerializationFeature.INDENT_OUTPUT);
        String strByJsonTypeResolver = objectMapper.writeValueAsString(mapData);
        System.out.println(strByJsonTypeResolver);

        // 32. @JsonTypeIdResolver
        List<JavaType> types = new ArrayList<JavaType>();
        CustomBean.CustomResolver.initTypes = types;
        String jsonByTypeIdResolver = objectMapper.writeValueAsString(new CustomBean[] { new CustomBean.CustomBeanImpl(28) });
        System.out.println(jsonByTypeIdResolver);

        types = new ArrayList<JavaType>();
        CustomBean.CustomResolver.initTypes = types;
        CustomBean[] result = objectMapper.readValue(jsonByTypeIdResolver, CustomBean[].class);
        System.out.println(result);
    }
}
